﻿using UnityEngine;
using System.Collections;
using WebSocketSharp;
using System;

/// <summary>
/// 网络控制器
/// </summary>
public class NetIOController : BaseController {

    /// <summary>
    /// 单例
    /// </summary>
    private static NetIOController _inst;

    public static NetIOController inst { get { return _inst; } }

    /// <summary>
    /// WebSocket连接
    /// </summary>
    private WebSocket _webSock;

    /// <summary>
    /// 消息队列
    /// </summary>
    private Queue _msgQueue;

    /// <summary>
    /// 是否就绪
    /// </summary>
    private bool _ready;

    public bool ready { get { return _ready; } }

    /// <summary>
    /// 是否正在连接
    /// </summary>
    bool _connecting;

    /// <summary>
    /// 是否连接到游戏服务器
    /// </summary>
    public bool _isGame;
    public bool isGame { get { return _isGame; } set { _isGame = value; } }

    ///////////////////////////////////////////////////////////////////////////

    protected override void InitData()
    {
        base.InitData();

        _msgQueue = new Queue();
        _ready = false;
        _connecting = false;
        _inst = this;
    }

    protected override void DestroyData()
    {
        base.DestroyData();

        if (_webSock != null)
        {
            _webSock.Close();
        }
    }

    ///////////////////////////////////////////////////////////////////////////

    void EnqueueMessage(IOMessage message)
    {
        lock (_msgQueue)
        {
            _msgQueue.Enqueue(message);
        }
    }

    public IOMessage DequeueMessage()
    {
        lock (_msgQueue)
        {
            if (_msgQueue.Count > 0)
            {
                return (IOMessage)_msgQueue.Dequeue();
            }
        }

        return null;
    }

    /// <summary>
    /// 连接到服务器
    /// </summary>
    /// <param name="url">服务器地址</param>
    public void Connect(string url)
    {
        if (!_connecting)
        {
            _connecting = true;

            if (_webSock != null)
            {
                if (url == null)
                {
                    url = _webSock.Url.ToString();
                }
                _webSock.CloseAsync();
            }

            DebugInfo.Log("正在连接：" + url);

            _webSock = new WebSocket(url, "default-protocol");
            _webSock.OnOpen += OnWsOpen;
            _webSock.OnMessage += OnWsMessage;
            _webSock.OnError += OnWsError;
            _webSock.OnClose += OnWsClosed;

            _webSock.ConnectAsync();
        }
    }

    /// <summary>
    /// 连接到新地址
    /// </summary>
    /// <param name="url"></param>
    public void ConnectToNewURL(string url)
    {
        _webSock.SetUrl(url, "default-protocol");
        _webSock.CloseAsync();
    }

    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="message">消息</param>
    public void SendMessage(IOMessage message)
    {
        if (this._ready)
        {
            string jsonToSend = message.ToJSON();
            _webSock.SendAsync(jsonToSend, sendOk => {
                if (sendOk)
                {
                    DebugInfo.Log("发送: " + jsonToSend);
                }
                else
                {
                    DebugInfo.Log("发送数据失败");
                }
            });
        }
        else
        {
            DebugInfo.Log("连接未就绪");
        }
    }

    /// <summary>
    /// 与服务器的连接被打开
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void OnWsOpen(object sender, EventArgs e)
    {
        DebugInfo.Log("连接到服务器 " + _webSock.Url);
        _ready = true;
        _connecting = false;
        EnqueueMessage(new IOMessage(IOCmds.WS_CONN_OPEN));
    }

    /// <summary>
    /// 收到消息
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void OnWsMessage(object sender, MessageEventArgs e)
    {
        DebugInfo.Log("收到: " + e.Data);
        EnqueueMessage(ParseMessage(e.Data));
    }

    void OnWsError(object sender, WebSocketSharp.ErrorEventArgs e)
    {
        EnqueueMessage(new IOMessage(IOCmds.WS_CONN_ERROR));
    }

    void OnWsClosed(object sender, CloseEventArgs e)
    {
        DebugInfo.Log("与服务器的网络连接被关闭");

        _connecting = false;
        EnqueueMessage(new IOMessage(IOCmds.WS_CONN_CLOSED));
    }

    IOMessage ParseMessage(string data)
    {
        Hashtable hashData = (Hashtable)MiniJSON.JsonDecode(data);
        int code = Convert.ToInt32(hashData["code"]);
        int state = IOStates.STATE_OK;
        if (hashData.ContainsKey("state"))
        {
            state = Convert.ToInt32(hashData["state"]);
        }
        HashtableEx args = new HashtableEx();
        if (hashData.ContainsKey("args"))
        {
            args.SetData(hashData["args"] as Hashtable);
        }
        return new IOMessage(code, state, args);
    }
}
